// let proto = require('../proto/ProtoMsgV1_pb.js')
import proto from '../proto/ProtoMsgV1_pb.js';
import LoginMsgBuilder from '../protoBuilder/LoginMsgBuilder.js'
import P2PMessageBuilder from '../protoBuilder/P2PMessageBuilser.js'
import ProtobufDecoder from '../code/ProtobufDecoder.js';
import HeartBeatMsgBuilder from '../protoBuilder/HeartBeatMsgBuilder.js';
import MsgReceiveAckBuilder from '../protoBuilder/MsgReceiveAckBuilder.js'

import {pullConversationList} from '../api/conversation.js'
import {getSingleUserInfo} from '../api/user.js'
import {getMsgList} from '../api/messageHistory.js'

// 10 seconds
const loginTimeout = 10 * 1000
// 10 seconds
const heartbeatInterval = 10 * 1000
// 第一次监听socket
let firstMonitorSocket = false;

/**
 * 状态
 */
export const State = {
	// 初始化
	INIT: 1,
	// 连接
	CONNECTING: 2,
	// 连接结束
	CONNECTED: 3,
	// 重连中
	RECONNECTING: 4,
	// 关闭中
	CLOSEING: 5,
	// 关闭
	CLOSED: 6,
}

export let sleep = async (second, Unit = TimeUnit.Second) => {
	return new Promise((resolve, _) => {
		setTimeout(() => {
			resolve()
		}, second * Unit)
	})
}

const ImClient = {
	// 连接地址
	url: "",
	// 用户id
	userId: '',
	// 平台类型
	platformType: proto.PlatformType.WEB,
	// 设备号
	imei: '',
	sessionId: '-1',
	// 监听
	listeners: null,
	// 
	appId: '',
	// 用户token
	userSign: '',
	// 设备号长度
	imeiLength: 0,
	// 连接状态
	state: State.INIT,
	socketTask: null,


	/**
	 * 是否初始化
	 */
	isInit: function() {
		return this.state == State.CONNECTING
	},

	/**
	 * 初始化连接
	 * @param {Object} websocketUrl
	 * @param {Object} appId
	 * @param {Object} userId
	 * @param {Object} userSign  
	 * @param {Object} imListeners
	 */
	init: async function(websocketUrl, appId, userId, userSign, imListeners) {
		
		// 基础信息
		const deviceId = uni.getDeviceInfo().deviceId
		console.log("设备信息：", deviceId);
		this.url = websocketUrl;
		this.appId = appId;
		this.userId = userId;
		this.imei = deviceId;
		this.userSign = userSign;
		this.listeners = imListeners;

		// 连接websocket
		this.socketTask = uni.connectSocket({
			url: websocketUrl,
			success: (res) => {
				console.log('connectSocket success')
			}
		})

		// 打开连接
		this.socketTask.onOpen(res => {
			if (this.socketTask.OPEN == 1) {
				console.log('websocket连接打开');
				// 执行登录
				let msg = LoginMsgBuilder.build(this.appId, this.userId, this.imei, this.userSign);
				this.sendMsg(msg);
			}
		})

		// 注册监听服务器发送回调的消息
		this.socketTask.onMessage(evt => {
			const pkg = ProtobufDecoder.decode(evt.data)
			// todo: 这边写各种消息的处理器，以及注册为钩子
			// console.log('消息onMessage：', pkg)
			
			if (pkg.getType() == proto.HeadType.LOGIN_RESPONSE) {
				console.log('登录成功响应')
				this.handlerLoginResp(pkg);
			} else if (pkg.getType() == proto.HeadType.LOGOUT_RESPONSE) {
				// 退出登录响应
				console.log('退出登录响应')
			} else if (pkg.getType() == proto.HeadType.HEART_BEAT) {
				// 心跳
				console.log('服务端心跳')
			} else if (pkg.getType() == proto.HeadType.MESSAGE_RESPONSE) {
				// 单聊响应
				console.log('单聊响应')
			} else if (pkg.getType() == proto.HeadType.MESSAGE_NOTIFICATION) {
				// 系统通知
				console.log('系统通知')
			} else if (pkg.getType() == proto.HeadType.MESSAGE_GROUP_RESPONSE) {
				// 群聊响应
				console.log('群聊响应')
			} else if (pkg.getType() == proto.HeadType.MESSAGE_ACK) {
				// im接受消息ack
				console.log('im接受消息ack')
			} else if (pkg.getType() == proto.HeadType.MESSAGE_RECEIVE_ACK) {
				console.log('用户接受消息ack')
			} else if (pkg.getType() == proto.HeadType.MESSAGE_REQUEST) {
				console.log('用户接受单聊消息')
				this.handlerMsgReq(pkg);
			}
		});
	},

	// // 自动重连
	// errorHandler: async function(error, req) {
	//     // 如果是主动断开连接，就没有必要自动重连
	//     // 比如收到被踢，或者主动调用logout()方法
	//     if (this.state == State.CLOSED || this.state == State.CLOSEING) {
	//         return
	//     }
	//     this.state = State.RECONNECTING
	// 	// 钩子
	//     this.listeners.onSocketReConnectEvent();
	//     // 重连10次
	//     for (let index = 0; index < 10; index++) {
	//         await sleep(3)
	//         try {
	//             console.log('SDK重连')
	//             // let { success, err } = await this.login()
	//             this.socketTask.send({
	//             	data: msg,
	//             	success: (res) => {
	//             		console.log('==========websocket发送消息完成==========', res)
	//             	},
	//             	complete: () => {
	//             		console.log('==========websocket发送消息完成complete==========')
	//             	}
	//             })


	//         } catch (error) {

	//         }
	//     }
	//     this.onclose("SDK重连 timeout")
	// },

	/**
	 * 关闭
	 * @param {Object} reason 
	 */
	onclose: function(reason) {
		if (this.state == State.CLOSED) {
			return
		}
		this.state = State.CLOSED

		console.log("connection closed due to " + reason)
		this.socketTask = unll;
		this.userId = ""

		// 加入socket 关闭事件

		this.listeners.onSocketCloseEvent();
	},
	
	/**
	 * 心跳
	 */
	heartbeatLoop: function() {
	    let start = Date.now()
	    let loop = () => {
	        if (this.state != State.CONNECTED) {
	            console.log("heartbeatLoop exited")
	            return
	        }
	        if (Date.now() - start >= heartbeatInterval) {
	            // console.log(`>>> send ping ;`);
	            start = Date.now();
	            const heartBeatMsg = HeartBeatMsgBuilder.build(this.appId, this.userId, this.userSign, this.sessionId);
				this.sendMsg(heartBeatMsg);
	        }
	        setTimeout(loop, 500)
	    }
	    setTimeout(loop, 500)
	},
	
	/**
	 * 发送消息
	 * @param {Object} msg
	 */
	sendMsg(msg) {
		this.socketTask.send({
			data: msg,
			success: (res) => {
				// console.log('==========websocket发送消息完成==========')
			}
		})
	},
	
	/**
	 * 登录成功处理器
	 * @param {Object} pkg
	 */
	handlerLoginResp(pkg) {
		// 登录响应
		console.log('登录响应');
		const loginResp = pkg.getLoginResponse();
		
		if (loginResp.getInfo() == 'Success') {
			console.log('SDK登录成功')
			// 更新会话ID
			this.sessionId = pkg.getSessionId();
			if (!firstMonitorSocket) {
				firstMonitorSocket = true;
			}
		
			// 错误监听
			this.socketTask.onError(evt => {
				console.log('websocket发生错误:', evt)
				this.listeners.onSocketErrorEvent(evt)
				// todo: 重连
			});
		
			// 可以添加 onClose 事件监听器来处理连接关闭的情况
			this.socketTask.onClose(res => {
				console.log('WebSocket连接关闭:', res);
				if (this.state == State.CLOSEING) {
					this.onclose("logout")
					return
				}
				this.listeners.onSocketCloseEvent();
				
				// todo: 重连
			});
			
			
			// 连接成功，更新状态
			this.state = State.CONNECTED;
			this.listeners.onLogin(this.userId);
			
			// 心跳
			this.heartbeatLoop();
		}
	},
	
	/**
	 * 用户接收单聊消息
	 * @param {Object} pkg
	 */
	handlerMsgReq(pkg) {
		console.log('处理接受的单聊消息：', pkg)
		const msgack = MsgReceiveAckBuilder.build(
			this.appId, 
			this.userId, 
			pkg.getMessageRequest().getFrom(), 
			this.sessionId, 
			pkg.getMessageRequest().getMsgId()
		);
		this.sendMsg(msgack);
		let msg = {
			fromId: pkg.getMessageRequest().getFrom(),
			toId: pkg.getMessageRequest().getTo(),
			ownerId: pkg.getMessageRequest().getFrom(),
			messageTime: Date.now(),
			createTime: Date.now(),
			messageBody: pkg.getMessageRequest().getContent()
		}
		this.listeners.onP2PMessage(msg);
	},
	
	sendP2PMsgTest(userId, contend) {
		const msg = P2PMessageBuilder.build(this.appId, this.sessionId, this.userId, userId, contend)
		
		this.socketTask.send({
			data: msg,
			success: (res) => {
				// console.log('==========websocket发送消息完成==========')
			}
		})
	},
	
	pullConversationList() {
		return pullConversationList({
			appId: this.appId,
			operator: this.userId
		});
	},
	getSingleUser(to) {
		return getSingleUserInfo({
			appId: this.appId,
			userId: to
		})
	},
	getMsgList(toId) {
		return getMsgList({
			operator: this.userId,
			appId: this.appId,
			toId: toId,
			fromId: this.userId
		})
	}
}

export default ImClient;